package com.ecr.hub.front.bean.managed;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.faces.model.SelectItem;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.ecr.hub.front.bean.AbstractManagedBean;
import com.ecr.hub.model.enumeration.HubBundleType;
import com.ecr.hub.model.enumeration.HubLading;
import com.ecr.hub.model.enumeration.HubObjectActive;
import com.ecr.hub.model.enumeration.HubSillonType;
import com.ecr.hub.model.enumeration.HubStack;
import com.ecr.hub.model.enumeration.HubWagonRiv;
import com.ecr.hub.model.enumeration.HubWagonTrailer;
import com.ecr.hub.service.destination.IDestinationManager;
import com.ecr.hub.service.hub.IHubManager;
import com.ecr.hub.service.rail.IRailManager;
import com.ecr.hub.service.user.IUserManager;
import com.ecr.hub.util.LabelUtils;
import com.ecr.hub.util.ManagedBeanUtils;

@Controller("repositoryManaged")
@Scope("application")
public class RepositoryManagedBean extends AbstractManagedBean {

	private static final long serialVersionUID = 1L;

	// Pour les wagons non référencés la taille par défaut à appliquer.
	public static final float DEFAULT_WAGON_TOTAL_LENGTH = (float) 26.5;

	// La liste des rôles.
	private List<SelectItem> lstRoles;
	// La liste des faisceaux.
	private List<SelectItem> lstBundles;
	// La liste des destinations.
	private List<SelectItem> lstDestinations;
	// La liste des destinations avec id externe.
	private List<SelectItem> lstDestinationsExtId;
	// La liste des voies de tri.
	private List<SelectItem> lstSortRails;
	// La liste des voies de formation.
	private List<SelectItem> lstAllRails;
	// Liste des statuts pour un wagon.
	private List<SelectItem> lstWagonStatus;
	// Liste des statuts pour une locomotive.
	private List<SelectItem> lstLocoStatus;
	// Une simple liste pour les positions.
	private List<SelectItem> lstPositions;
	// La liste des types pour les wagons.
	private List<SelectItem> lstWagonTypes;
	// La liste des types pour les locomotives.
	private List<SelectItem> lstLocoTypes;
	// Liste simple pour le RIV (oui/non);
	private List<SelectItem> lstWagonRiv;
	// Liste simple pour le sens du départ.
	private List<SelectItem> lstStack;
	// Liste simple pour le chargement.
	private List<SelectItem> lstWagonLading;
	// Liste simple pour les types de sillon.
	private List<SelectItem> lstSillonTypes;
	// Liste simple stricte pour les types de sillon.
	private List<SelectItem> lstSillonStrictTypes;

	// Le manager pour les utilisateurs.
	@Resource(name = "userManager")
	private IUserManager userManager;
	// Le manager pour les voies.
	@Resource(name = "railManager")
	private IRailManager railManager;
	// Le manager pour les destinations.
	@Resource(name = "destinationManager")
	private IDestinationManager destinationManager;
	// Le manager pour le hub.
	@Resource(name = "hubManager")
	private IHubManager hubManager;

	/**
	 * Récupération de la lise des rôles. A utiliser pour les listes
	 * déroulantes.
	 */
	public List<SelectItem> getLstRoles() {
		try {
			if (lstRoles == null) {
				lstRoles = ManagedBeanUtils.buildSelectCollection(
						userManager.getAllRoles(), "label", "id");
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstRoles;
	}

	/**
	 * Récupération de la liste des types de faisceaux. Récupération de
	 * l'ensemble des enregistrements dans la table hub_bundle_type. A utiliser
	 * pour les listes déroulantes.
	 */
	public List<SelectItem> getLstTypeBundles() {
		try {
			if (lstBundles == null) {
				lstBundles = ManagedBeanUtils.buildSelectCollection(
						railManager.getListTypeBundle(), "label", "id");
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstBundles;
	}

	/**
	 * Récupération de la liste des destinations. Récupération de l'ensemble des
	 * enregistrements de la table hub_destinations. A utiliser pour les listes
	 * déroulantes.
	 */
	public List<SelectItem> getLstDestinations() {
		try {
			if (lstDestinations == null) {
				lstDestinations = new ArrayList<SelectItem>();
				lstDestinations.add(new SelectItem("-1", LabelUtils
						.getLabel("select.title.destination")));
				lstDestinations.addAll(ManagedBeanUtils.buildSelectCollection(
						destinationManager.getAllList(), "label", "id"));
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstDestinations;
	}

	/**
	 * Récupération de la liste des destinations avec les identifiants externes
	 * des destinations. Récupération de l'ensemble des enregistrements de la
	 * table hub_destinations. A utiliser pour les listes déroulantes.
	 */
	public List<SelectItem> getLstDestinationsExtId() {
		try {
			if (lstDestinationsExtId == null) {
				lstDestinationsExtId = new ArrayList<SelectItem>();
				lstDestinationsExtId.add(new SelectItem("-1", LabelUtils
						.getLabel("select.title.destination")));
				lstDestinationsExtId.addAll(ManagedBeanUtils
						.buildSelectCollection(destinationManager.getAllList(),
								"label", "extId"));
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstDestinationsExtId;
	}

	/**
	 * Récupération de la liste des voies pour le tri. On récupère l'ensemble
	 * des voies actives dans la table hub_rail dont le type de faisceau est
	 * tri.
	 */
	public List<SelectItem> getLstSortRails() {
		try {
			if (lstSortRails == null) {
				String prefix = LabelUtils.getLabel("hub.rail") + " : ";
				lstSortRails = ManagedBeanUtils.buildSelectCollection(
						railManager.getListByTypeBundle(
								HubBundleType.SORT.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
						"id", prefix);
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstSortRails;
	}

	/**
	 * Récupération de la liste des voies pour la formation. On récupère
	 * l'ensemble des voies actives dans la table hub_rail dont le type de
	 * faisceau est tri,formation, départ.
	 */
	public List<SelectItem> getLstAllRails() {
		try {
			if (lstAllRails == null) {
				String prefix = LabelUtils.getLabel("hub.rail") + " : ";
				lstAllRails = new ArrayList<SelectItem>();
				// La reception
				lstAllRails.add(new SelectItem(-1, LabelUtils
						.getLabel("select.title.arrival")));
				lstAllRails.addAll(ManagedBeanUtils.buildSelectCollection(
						railManager.getListByTypeBundle(
								HubBundleType.ARRIVAL.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
						"id", prefix));
				lstAllRails.add(new SelectItem(-2, ""));
				// Le tri.
				lstAllRails.add(new SelectItem(-3, LabelUtils
						.getLabel("select.title.sort")));
				lstAllRails.addAll(ManagedBeanUtils.buildSelectCollection(
						railManager.getListByTypeBundle(
								HubBundleType.SORT.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
						"id", prefix));
				lstAllRails.add(new SelectItem(-4, ""));
				// La formation.
				lstAllRails.add(new SelectItem(-5, LabelUtils
						.getLabel("select.title.formation")));
				lstAllRails.addAll(ManagedBeanUtils.buildSelectCollection(
						railManager.getListByTypeBundle(
								HubBundleType.FORMATION.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
						"id", prefix));
				lstAllRails.add(new SelectItem(-6, ""));
				// Les départs.
				lstAllRails.add(new SelectItem(-7, LabelUtils
						.getLabel("select.title.departure")));
				lstAllRails.addAll(ManagedBeanUtils.buildSelectCollection(
						railManager.getListByTypeBundle(
								HubBundleType.DEPARTURE.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
						"id", prefix));
				lstAllRails.add(new SelectItem(-8, ""));
				// RVB
				List<SelectItem> l_rvb = ManagedBeanUtils
						.buildSelectCollection(railManager.getListByTypeBundle(
								HubBundleType.RVB.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
								"id", prefix);
				if (l_rvb != null && l_rvb.size() > 0) {
					lstAllRails.add(new SelectItem(-9, LabelUtils
							.getLabel("select.title.rvb")));
					lstAllRails.addAll(l_rvb);
					lstAllRails.add(new SelectItem(-10, ""));
				}

				// CMT
				List<SelectItem> l_cmt = ManagedBeanUtils
						.buildSelectCollection(railManager.getListByTypeBundle(
								HubBundleType.CMT.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
								"id", prefix);
				if (l_cmt != null && l_cmt.size() > 0) {
					lstAllRails.add(new SelectItem(-11, LabelUtils
							.getLabel("select.title.cmt")));
					lstAllRails.addAll(l_cmt);
					lstAllRails.add(new SelectItem(-12, ""));
				}

				// EVEN
				List<SelectItem> l_even = ManagedBeanUtils
						.buildSelectCollection(railManager.getListByTypeBundle(
								HubBundleType.EVEN_RELAY.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
								"id", prefix);
				if (l_even != null && l_even.size() > 0) {
					lstAllRails.add(new SelectItem(-13, LabelUtils
							.getLabel("select.title.even.pair")));
					lstAllRails.addAll(l_even);
					lstAllRails.add(new SelectItem(-14, ""));
				}

				// ODD
				List<SelectItem> l_odd = ManagedBeanUtils
						.buildSelectCollection(railManager.getListByTypeBundle(
								HubBundleType.ODD_RELAY.getValue(),
								HubObjectActive.ACTIVE.getValue()), "number",
								"id", prefix);
				if (l_odd != null && l_odd.size() > 0) {
					lstAllRails.add(new SelectItem(-15, LabelUtils
							.getLabel("select.title.odd.pair")));
					lstAllRails.addAll(l_odd);
				}
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstAllRails;
	}

	/**
	 * Récupération de la liste des statuts pour un wagon.
	 */
	public List<SelectItem> getLstWagonStatus() {
		try {
			if (lstWagonStatus == null) {
				lstWagonStatus = new ArrayList<SelectItem>();
				lstWagonStatus.add(new SelectItem(-1, LabelUtils
						.getLabel("select.title.status")));
				lstWagonStatus.addAll(ManagedBeanUtils.buildSelectCollection(
						hubManager.getListWagonStatus(HubWagonTrailer.TRAILER),
						"label", "id"));
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstWagonStatus;
	}

	/**
	 * Récupération de la liste des statuts pour une locomotive.
	 */
	public List<SelectItem> getLstLocoStatus() {
		try {
			if (lstLocoStatus == null) {
				lstLocoStatus = new ArrayList<SelectItem>();
				lstLocoStatus.add(new SelectItem(-1, LabelUtils
						.getLabel("select.title.status")));
				lstLocoStatus
						.addAll(ManagedBeanUtils.buildSelectCollection(
								hubManager
										.getListWagonStatus(HubWagonTrailer.NOT_TRAILER),
								"label", "id"));
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstLocoStatus;
	}

	/**
	 * Récupération de la liste des types pour un wagon.
	 */
	public List<SelectItem> getLstWagonTypes() {
		try {
			if (lstWagonTypes == null) {
				lstWagonTypes = new ArrayList<SelectItem>();
				lstWagonTypes.add(new SelectItem(-1, LabelUtils
						.getLabel("select.title.type")));
				lstWagonTypes.addAll(ManagedBeanUtils.buildSelectCollection(
						hubManager.getListWagonTypes(HubWagonTrailer.TRAILER),
						"label", "id"));
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstWagonTypes;
	}

	/**
	 * Récupération de la liste des types pour une locomotive.
	 */
	public List<SelectItem> getLstLocoTypes() {
		try {
			if (lstLocoTypes == null) {
				lstLocoTypes = new ArrayList<SelectItem>();
				lstLocoTypes.add(new SelectItem(-1, LabelUtils
						.getLabel("select.title.type")));
				lstLocoTypes
						.addAll(ManagedBeanUtils.buildSelectCollection(
								hubManager
										.getListWagonTypes(HubWagonTrailer.NOT_TRAILER),
								"label", "id"));
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
		return lstLocoTypes;
	}

	/**
	 * Cette liste permet juste de récupérer une liste de positions. Le fait de
	 * passer par une liste permet d'éviter les erreurs de saisie et surtout de
	 * décrémenter la position de 1 de manière transparente pour l'utilisateur.
	 * De plus, il semble que l'on ait un bug avec les boîtes de texte par
	 * rapport à la saisie du commentaire.
	 */
	public List<SelectItem> getLstPositions() {
		if (lstPositions == null) {
			lstPositions = new ArrayList<SelectItem>();
			lstPositions.add(new SelectItem(-1, "------"));
			lstPositions.add(new SelectItem(0, "1"));
			lstPositions.add(new SelectItem(1, "2"));
			lstPositions.add(new SelectItem(2, "3"));
			lstPositions.add(new SelectItem(3, "4"));
			lstPositions.add(new SelectItem(4, "5"));
			lstPositions.add(new SelectItem(5, "6"));
			lstPositions.add(new SelectItem(6, "7"));
			lstPositions.add(new SelectItem(7, "8"));
			lstPositions.add(new SelectItem(8, "9"));
			lstPositions.add(new SelectItem(9, "10"));
			lstPositions.add(new SelectItem(10, "11"));
			lstPositions.add(new SelectItem(11, "12"));
			lstPositions.add(new SelectItem(12, "13"));
			lstPositions.add(new SelectItem(13, "14"));
			lstPositions.add(new SelectItem(14, "15"));
			lstPositions.add(new SelectItem(15, "16"));
			lstPositions.add(new SelectItem(16, "17"));
			lstPositions.add(new SelectItem(17, "18"));
			lstPositions.add(new SelectItem(18, "19"));
			lstPositions.add(new SelectItem(19, "20"));
			lstPositions.add(new SelectItem(20, "21"));
			lstPositions.add(new SelectItem(21, "22"));
			lstPositions.add(new SelectItem(22, "23"));
			lstPositions.add(new SelectItem(23, "24"));
			lstPositions.add(new SelectItem(24, "25"));
			lstPositions.add(new SelectItem(25, "26"));
			lstPositions.add(new SelectItem(26, "27"));
			lstPositions.add(new SelectItem(27, "28"));
			lstPositions.add(new SelectItem(28, "29"));
			lstPositions.add(new SelectItem(29, "30"));
		}
		return lstPositions;
	}

	/**
	 * Liste simple qui retourne juste OUI/NON pour savoir si un wagon est RIV
	 * ou non.
	 */
	public List<SelectItem> getLstWagonRiv() {
		if (lstWagonRiv == null) {
			lstWagonRiv = new ArrayList<SelectItem>();
			lstWagonRiv.add(new SelectItem("-1", LabelUtils
					.getLabel("select.title.riv")));
			lstWagonRiv.add(new SelectItem(HubWagonRiv.NOT_RIV.getValue(),
					HubWagonRiv.NOT_RIV.getValue()));
			lstWagonRiv.add(new SelectItem(HubWagonRiv.RIV.getValue(),
					HubWagonRiv.RIV.getValue()));
		}
		return lstWagonRiv;
	}

	/**
	 * Liste simple qui retourne juste les différents types pour le chargement
	 * (on ne prend pas mixte qui concerne les trains et non les wagons).
	 */
	public List<SelectItem> getLstWagonLading() {
		if (lstWagonLading == null) {
			lstWagonLading = new ArrayList<SelectItem>();
			lstWagonLading.add(new SelectItem("-1", LabelUtils
					.getLabel("select.title.lading")));
			lstWagonLading.add(new SelectItem(HubLading.LOADED.getValue(),
					HubLading.LOADED.getValue()));
			lstWagonLading.add(new SelectItem(HubLading.EMPTY.getValue(),
					HubLading.EMPTY.getValue()));
		}
		return lstWagonLading;
	}

	/**
	 * Liste simple pour connaitre les sens d'empilement ou de dépilement des
	 * wagons. Deux sens sont possibles NORD et SUD.
	 */
	public List<SelectItem> getLstStack() {
		if (lstStack == null) {
			lstStack = new ArrayList<SelectItem>();
			lstStack.add(new SelectItem(HubStack.POS_BEGIN.getValue(), "Sud"));
			lstStack.add(new SelectItem(HubStack.POS_END.getValue(), "Nord"));
		}
		return lstStack;
	}

	/**
	 * Liste simple pour obtenir les différents types de sillon. Trois types
	 * sont possibles : Tous, arrivée, départ.
	 */
	public List<SelectItem> getLstSillonTypes() {
		if (lstSillonTypes == null) {
			lstSillonTypes = new ArrayList<SelectItem>();
			lstSillonTypes.add(new SelectItem(HubSillonType.ALL.getValue(),
					LabelUtils.getLabel("sillon.type.all")));
			lstSillonTypes.add(new SelectItem(HubSillonType.ARRIVAL.getValue(),
					LabelUtils.getLabel("sillon.type.arrival")));
			lstSillonTypes.add(new SelectItem(HubSillonType.DEPARTURE
					.getValue(), LabelUtils.getLabel("sillon.type.departure")));
		}
		return lstSillonTypes;
	}

	/**
	 * Liste stricte simple pour obtenir les différents types de sillon. Deux
	 * types sont possibles : arrivée, départ.
	 */
	public List<SelectItem> getLstSillonStrictTypes() {
		if (lstSillonStrictTypes == null) {
			lstSillonStrictTypes = new ArrayList<SelectItem>();
			lstSillonStrictTypes.add(new SelectItem("-1", LabelUtils
					.getLabel("select.title.type")));
			lstSillonStrictTypes.add(new SelectItem(HubSillonType.ARRIVAL
					.getValue(), LabelUtils
					.getLabel("sillon.type.strict.arrival")));
			lstSillonStrictTypes.add(new SelectItem(HubSillonType.DEPARTURE
					.getValue(), LabelUtils
					.getLabel("sillon.type.strict.departure")));
		}
		return lstSillonStrictTypes;
	}

	/**
	 * Demande le rafraichissement de l'ensemble des listes présentes dans le
	 * bean. Comme il s'agit de listes mises à jour par un changement de
	 * configuration (rare) on ne cherche pas à spécialement à affiner le choix
	 * de la liste à réinitialiser et on demande la réinitialisation totale de
	 * certaines listes déroulantes. Récupération du bean dans le scope
	 * application et effacement des listes.
	 */
	public static void refresh() {

		RepositoryManagedBean repository = (RepositoryManagedBean) ManagedBeanUtils
				.getExternalContext().getApplicationMap()
				.get("repositoryManaged");
		if (null != repository) {
			repository.lstDestinations = null;
			repository.lstDestinationsExtId = null;
			repository.lstAllRails = null;
			repository.lstSortRails = null;
		}
	}
}
